package com.yhd.gmall.order.controller;

import com.alibaba.fastjson.JSON;
import com.yhd.gmall.cart.client.CartFeignClient;
import com.yhd.gmall.common.result.Result;
import com.yhd.gmall.common.util.AuthContextHolder;
import com.yhd.gmall.model.cart.CartInfo;
import com.yhd.gmall.model.order.OrderDetail;
import com.yhd.gmall.model.order.OrderInfo;
import com.yhd.gmall.model.user.UserAddress;
import com.yhd.gmall.order.service.OrderService;
import com.yhd.gmall.product.client.ProductFeignClient;
import com.yhd.gmall.user.client.UserFeignClient;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author yhd
 * @createtime 2020/9/30 10:45
 */
@RestController
@RequestMapping("api/order")
public class OrderApiController {

    @Autowired
    private UserFeignClient userFeignClient;

    @Autowired
    private CartFeignClient cartFeignClient;

    @Autowired
    private OrderService orderService;

    @Autowired
    private ProductFeignClient productFeignClient;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    /**
     * 确认订单
     */
    @GetMapping("auth/trade")
    public Result<Map<String, Object>> trade(HttpServletRequest request) {
        //获取到用户id
        String userId = AuthContextHolder.getUserId(request);
        //获取用户地址
        List<UserAddress> userAddressList = userFeignClient.findUserAddressListByUserId(userId);

        //获取到用户想要购买的商品
        List<CartInfo> cartList = cartFeignClient.getCartCheckedList(userId);

        if (!CollectionUtils.isEmpty(cartList) && cartList.size() > 0) {
            //生成订单明细
            List<OrderDetail> detailList = new ArrayList<>();

            for (CartInfo cartInfo : cartList) {
                OrderDetail orderDetail = new OrderDetail();
                orderDetail.setSkuId(cartInfo.getSkuId());
                orderDetail.setSkuName(cartInfo.getSkuName());
                orderDetail.setImgUrl(cartInfo.getImgUrl());
                orderDetail.setSkuNum(cartInfo.getSkuNum());
                orderDetail.setOrderPrice(cartInfo.getSkuPrice());
                detailList.add(orderDetail);
            }
            //生成订单
            OrderInfo orderInfo = new OrderInfo();
            orderInfo.setOrderDetailList(detailList);
            orderInfo.sumTotalAmount();
            Map<String, Object> result = new HashMap<>();
            //考虑幂等性
            String tradeNo = orderService.getTradeNo(userId);
            result.put("tradeNo",tradeNo);
            result.put("userAddressList", userAddressList);
            result.put("detailArrayList", detailList);
            // 保存总金额
            result.put("totalNum", detailList.size());
            result.put("totalAmount", orderInfo.getTotalAmount());
            return Result.ok(result);
        }
        return Result.fail();
    }

    /**
     * 提交订单
     */
    @PostMapping("auth/submitOrder")
    public Result submitOrder(@RequestBody OrderInfo orderInfo, HttpServletRequest request){

        // 获取到用户Id
        String userId = AuthContextHolder.getUserId(request);
        orderInfo.setUserId(Long.parseLong(userId));

        //获取前台流水号
        String tradeNo = request.getParameter("tradeNo");
        //比较
        boolean flag = orderService.checkTradeCode(userId, tradeNo);
        if (!flag){
            return Result.fail().message("不能重复提交订单！");
        }
        orderService.deleteTradeNo(userId);

        //验证
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        List<CompletableFuture> futureList=new ArrayList<>();
        List<String> errorList = new ArrayList<>();
        for (OrderDetail orderDetail:orderDetailList){
            CompletableFuture<Void> checkStock = CompletableFuture.runAsync(() -> {
                //验证库存
                boolean result = orderService.checkStock(orderDetail.getSkuId(), orderDetail.getSkuNum());
                if (!result){
                    errorList.add(orderDetail.getSkuName()+"库存不足！");
                }
            },threadPoolExecutor);
            futureList.add(checkStock);
            //验证价格
            CompletableFuture<Void> checkPrice = CompletableFuture.runAsync(() -> {
                BigDecimal skuPrice = productFeignClient.getSkuPrice(orderDetail.getSkuId());
                if (orderDetail.getOrderPrice().compareTo(skuPrice) != 0) {
                    // 重新查询价格！
                    cartFeignClient.loadCartCache(userId);
                    errorList.add(orderDetail.getSkuName()+"价格变动！");
                }
            }, threadPoolExecutor);
            futureList.add(checkPrice);
        }

        //合并线程
        CompletableFuture.allOf(futureList.toArray(new CompletableFuture[futureList.size()])).join();
        if (errorList.size()>0){
            return Result.fail().message(StringUtils.join(errorList,","));
        }

        // 验证通过，保存订单！
        Long orderId = orderService.saveOrderInfo(orderInfo);
        return Result.ok(orderId);
    }

    /**
     * 内部调用获取订单
     * @param orderId
     * @return
     */
    @GetMapping("inner/getOrderInfo/{orderId}")
    public OrderInfo getOrderInfo(@PathVariable(value = "orderId") Long orderId){
        return orderService.getById(orderId);
    }


    /**
     * 拆单业务
     * @param request
     * @return
     */
    @RequestMapping("orderSplit")
    public String orderSplit(HttpServletRequest request){
        String orderId = request.getParameter("orderId");
        String wareSkuMap = request.getParameter("wareSkuMap");

        // 拆单：获取到的子订单集合
        List<OrderInfo> subOrderInfoList = orderService.orderSplit(Long.parseLong(orderId),wareSkuMap);
        // 声明一个存储map的集合
        ArrayList<Map> mapArrayList = new ArrayList<>();
        // 生成子订单集合
        for (OrderInfo orderInfo : subOrderInfoList) {
            Map map = orderService.initWareOrder(orderInfo);
            // 添加到集合中！
            mapArrayList.add(map);
        }
        return JSON.toJSONString(mapArrayList);
    }
}
